package main

import (
	"crypto/tls"
	"fmt"
	"time"
)

func main() {

	fmt.Println("start: go 配置对象方案")
	srv01, _ := NewServerV2("localhost", 9000, nil)
	fmt.Printf("srv01 : %T value :%v\n ", srv01, srv01)

	conf := Config{Protocol: "tcp", Timeout: 60 * time.Second}
	srv02, _ := NewServerV2("localhost", 9000, &conf)
	fmt.Printf("srv02 : %T, value :%v\n ", srv02, srv02)
	fmt.Println("end: go 配置对象方案")

	fmt.Println("start: go 使用一个builder类来做包装")

	sb := ServerBuilder{}
	srv03 := sb.Create("127.0.0.1", 9000).WithProtocol("tcp").WithMaxConn(1024).WithTimeOut(30 * time.Second).Build()
	fmt.Printf("srv03: %T value :%v\n", srv03, srv03)

	fmt.Println("end: go 使用一个builder类来做包装")

	fmt.Println("start: go 使用 optional函数，实现配置化")

	srv04, _ := NewServerV3("localhost", 9000, Timeout(time.Second*30), MaxConns(1024), Protocol("udp"))
	fmt.Printf("srv04: %T value :%v \n", srv04, srv04)
	fmt.Println("end: go 使用 optional函数，实现配置化")
}

// 定义实体
type Server struct {
	Addr     string
	Port     int
	Protocol string
	Timeout  time.Duration
	MaxConns int
	TLS      *tls.Config
}

// 用不同的函数名来应对不同的配置选项
func NewDefaultServer(addr string, port int) (*Server, error) {
	return &Server{addr, port, "tcp", 30 * time.Second, 100, nil}, nil
}

func NewTLSServer(addr string, port int, tls *tls.Config) (*Server, error) {
	return &Server{addr, port, "tcp", 30 * time.Second, 100, tls}, nil
}

func NewServerWithTimeout(addr string, port int, timeout time.Duration) (*Server, error) {
	return &Server{addr, port, "tcp", timeout, 100, nil}, nil
}

func NewTLSServerWithMaxConnAndTimeout(addr string, port int, maxconns int, timeout time.Duration, tls *tls.Config) (*Server, error) {
	return &Server{addr, port, "tcp", 30 * time.Second, maxconns, tls}, nil
}

// 配置对象方案
type Config struct {
	Protocol string
	Timeout  time.Duration
	MaxConns int
	TLS      *tls.Config
}

type ServerV2 struct {
	Addr string
	Port int
	Conf *Config
}

func NewServerV2(addr string, port int, conf *Config) (*ServerV2, error) {
	return &ServerV2{addr, port, conf}, nil
}

// 使用一个builder类来做包装
type ServerBuilder struct {
	Server
}

func (sb *ServerBuilder) Create(addr string, port int) *ServerBuilder {
	sb.Server.Addr = addr
	sb.Server.Port = port
	//其它代码设置其它成员的默认值
	return sb
}
func (sb *ServerBuilder) WithProtocol(protocol string) *ServerBuilder {
	sb.Server.Protocol = protocol
	return sb
}
func (sb *ServerBuilder) WithMaxConn(maxconn int) *ServerBuilder {
	sb.Server.MaxConns = maxconn
	return sb
}
func (sb *ServerBuilder) WithTimeOut(timeout time.Duration) *ServerBuilder {
	sb.Server.Timeout = timeout
	return sb
}
func (sb *ServerBuilder) WithTLS(tls *tls.Config) *ServerBuilder {
	sb.Server.TLS = tls
	return sb
}
func (sb *ServerBuilder) Build() Server {
	return sb.Server
}

// functional options

type Option func(*Server)

func Protocol(p string) Option {
	return func(server *Server) {
		server.Protocol = p
	}
}

func Timeout(timeout time.Duration) Option {
	return func(server *Server) {
		server.Timeout = timeout
	}
}

func MaxConns(maxconns int) Option {
	return func(server *Server) {
		server.MaxConns = maxconns
	}
}

func TLS(tls *tls.Config) Option {
	return func(server *Server) {
		server.TLS = tls
	}
}

// 使用 optional函数，实现配置化
func NewServerV3(addr string, port int, options ...func(*Server)) (*Server, error) {
	srv := Server{
		Addr:     addr,
		Port:     port,
		Protocol: "tcp",
		Timeout:  30 * time.Second,
		MaxConns: 1000,
		TLS:      nil,
	}

	for _, option := range options {
		option(&srv)
	}

	return &srv, nil
}
